home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / edit / xvisrc.zip / OS2VIO.C < prev    next >
C/C++ Source or Header  |  1992-07-28  |  18KB  |  857 lines

  1. #ifndef lint
  2. static char *sccsid = "@(#)os2vio.c    2.1 (Chris & John Downey) 7/29/92";
  3. #endif
  4.  
  5. /***
  6.  
  7. * program name:
  8.     xvi
  9. * function:
  10.     PD version of UNIX "vi" editor, with extensions.
  11. * module name:
  12.     os2vio.c
  13.  
  14. * module function:
  15.     OS/2 system interface module.
  16.  
  17.     This is a character-based implementation using the VIO & KBD
  18.     families of system calls. It doesn't use the Presentation Manager
  19.     but, on OS/2 version 1.* at least, it can be made to work in a PM
  20.     shell window by using markexe (see makefile.os2).
  21.  
  22.     Like the MS-DOS version, this one saves the screen contents &
  23.     restores them when it exits.
  24.  
  25.     Currently, the mouse input code doesn't work, & so is commented
  26.     out. I suspect that, if we want to have both mouse & keyboard
  27.     input, we have to use a device monitor, or develop a real PM
  28.     implementation.
  29. * history:
  30.     STEVIE - ST Editor for VI Enthusiasts, Version 3.10
  31.     Originally by Tim Thompson (twitch!tjt)
  32.     Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
  33.     Heavily modified by Chris & John Downey
  34.  
  35. ***/
  36.  
  37. #include "xvi.h"
  38.  
  39. #define NOMOUSE
  40.  
  41. #ifdef __ZTC__
  42. /*
  43.  * Set default stack size.
  44.  *
  45.  * See i286.asm for an explanation of why it has to be so big.
  46.  */
  47. unsigned    _stack = 44 * 1024;
  48. #endif
  49.  
  50. /*
  51.  * These are globals which are set by the system interface or terminal
  52.  * interface module, & used for various purposes throughout the rest
  53.  * of xvi.
  54.  *
  55.  * Number of rows & columns in the current window.
  56.  */
  57. unsigned    Rows,
  58.         Columns;
  59. /*
  60.  * Current position for screen writes.
  61.  */
  62. unsigned char    virt_row,
  63.         virt_col;
  64. /*
  65.  * Screen cell (character & attribute): current colour is stored here.
  66.  */
  67. unsigned char    curcell [2];
  68.  
  69. /*
  70.  * Time of last keypress or mouse button press (or garbage if
  71.  * (keystrokes < PSVKEYS)).
  72.  *
  73.  * This should only be referenced within a thread's critical section.
  74.  * Referencing a 32-bit variable is not generally an atomic operation
  75.  * on the 80286.
  76.  */
  77. static volatile clock_t lastevent;
  78.  
  79. #ifndef NOMOUSE
  80.     /*
  81.      * This is FALSE if we don't appear to have a mouse driver.
  82.      */
  83.     static bool_t    usemouse;
  84.  
  85.     /*
  86.      * Our logical mouse handle.
  87.      */
  88.     static HMOU    mousenum;
  89.  
  90. #else    /* NOMOUSE */
  91. #   define    usemouse    FALSE
  92. #endif    /* NOMOUSE */
  93.  
  94. #ifndef NOMOUSE
  95.     /*
  96.      * Hide mouse cursor.
  97.      */
  98.     static void
  99.     hidemouse()
  100.     {
  101.     NOPTRRECT    r;
  102.  
  103.     r.row = r.col = 0;
  104.     r.cRow = Rows - 1;
  105.     r.cCol = Columns - 1;
  106.     (void) MouRemovePtr((PNOPTRRECT) &r, mousenum);
  107.     }
  108.  
  109. #endif    /* NOMOUSE */
  110.  
  111. /*
  112.  * Show mouse cursor. (This is for symmetry with hidemouse().)
  113.  */
  114. #define showmouse()    ((void) MouDrawPtr(mousenum))
  115.  
  116. static long    semvec [2];
  117.  
  118. /*
  119.  * This semaphore needs to be acquired by a thread before it enters a
  120.  * critical region.
  121.  */
  122. #define        control ((HSEM)(long FAR *)&semvec[0])
  123.  
  124. /*
  125.  * This semaphore is used for communication between the main thread &
  126.  * the thread which handles automatic buffer preservation. It should
  127.  * be clear when (keystrokes >= PSVKEYS), otherwise it should be set.
  128.  */
  129. #define        psvsema ((HSEM)(long FAR *)&semvec[1])
  130.  
  131. #ifndef NOMOUSE
  132.  
  133. static void
  134. mousehandler()
  135. {
  136.     for (;;) {
  137.     MOUEVENTINFO    m;
  138.     unsigned short    status;
  139.     clock_t        start;
  140.  
  141. #if 0
  142.     if (MouGetDevStatus((PUSHORT) &status, mousenum) != 0
  143.         ||
  144.         (status & (MOUSE_UNSUPPORTED_MODE | MOUSE_DISABLED))
  145.     ) {
  146.         hidemouse();
  147.         (void) MouClose(mousenum);
  148.         DosExit(EXIT_THREAD, 0);
  149.     }
  150. #endif
  151.     status = MOU_WAIT;
  152.     MouReadEventQue((PMOUEVENTINFO) &m, (PUSHORT) &status, mousenum);
  153.     /*
  154.      * If we don't get the control semaphore immediately,
  155.      * we do nothing. Delayed responses to mouse button
  156.      * presses could be confusing.
  157.      */
  158. #if 0
  159.     start = clock();
  160. #endif
  161.     if (DosSemRequest(control, SEM_IMMEDIATE_RETURN) != 0)
  162.         continue;
  163. #if 0
  164.     if (clock() != start) {
  165.         (void) fprintf(stderr, "mouse thread: %d\n", __LINE__);
  166.         DosSemClear(control);
  167.         continue;
  168.     }
  169. #endif
  170.     /*
  171.      * Start of critical section.
  172.      */
  173.     if (++keystrokes >= PSVKEYS)
  174.         lastevent = clock();
  175.     if (State == NORMAL &&
  176.         (m.fs & (MOUSE_BN1_DOWN | MOUSE_BN2_DOWN | MOUSE_BN3_DOWN))) {
  177.         hidemouse();
  178.         mouseclick(m.row, m.col);
  179.         showmouse();
  180.     }
  181.     /*
  182.      * End of critical section.
  183.      */
  184.     DosSemClear(control);
  185.     }
  186. }
  187.  
  188. #endif    /* NOMOUSE */
  189.  
  190. /*
  191.  * Macro to convert clock ticks to milliseconds.
  192.  */
  193. #if CLK_TCK == 1000
  194. #   define CLK2MS(c)        (c)
  195. #else
  196. #   if CLK_TCK < 1000
  197. #    define CLK2MS(c)    ((c) * (1000 / CLK_TCK))
  198. #   else
  199. #    define CLK2MS(c)    ((c) / (CLK_TCK / 1000))
  200. #   endif    /* CLK_TCK > 1000 */
  201. #endif    /* CLK_TCK != 1000 */
  202.  
  203. /*
  204.  * Number of keystrokes or mouse button presses since the last buffer
  205.  * preservation.
  206.  */
  207. volatile int        keystrokes;
  208.  
  209. /*
  210.  * This function handles automatic buffer preservation. It runs in its
  211.  * own thread, which is only awake when keystrokes >= PSVKEYS and the
  212.  * main thread is waiting for keyboard input. Even then, it spends
  213.  * most of its time asleep.
  214.  */
  215. static void FAR
  216. psvhandler()
  217. {
  218.     for (;;) {
  219.     long    sleeptime;
  220.  
  221.     DosSemWait(psvsema, SEM_INDEFINITE_WAIT);
  222.     DosSemRequest(control, SEM_INDEFINITE_WAIT);
  223.     /*
  224.      * Start of critical section.
  225.      */
  226.     if (keystrokes < PSVKEYS) {
  227.         sleeptime = 0;
  228.         /*
  229.          * If we haven't had at least PSVKEYS
  230.          * keystrokes, psvsema should be set.
  231.          */
  232.         DosSemSet(psvsema);
  233.     } else if ((sleeptime = (long) Pn(P_preservetime) * 1000 -
  234.               CLK2MS(clock() - lastevent)) <= 0) {
  235.         /*
  236.          * If Pn(P_presevetime) seconds haven't yet
  237.          * elapsed, sleep until they should have - but
  238.          * NOT within the critical section (!).
  239.          *
  240.          * Otherwise do automatic preserve.
  241.          *
  242.          * do_preserve() should reset keystrokes to 0.
  243.          */
  244.         (void) do_preserve();
  245.         sleeptime = 0;
  246.     }
  247.     /*
  248.      * End of critical section.
  249.      */
  250.     DosSemClear(control);
  251.     /*
  252.      * Sleep if we have to.
  253.      */
  254.     if (sleeptime != 0)
  255.         DosSleep(sleeptime);
  256.     }
  257. }
  258.  
  259. /*
  260.  * inchar() - get a character from the keyboard.
  261.  *
  262.  * Timeout not implemented yet for OS/2.
  263.  */
  264. int
  265. inchar(long mstimeout)
  266. {
  267.     for (;;) {
  268.     KBDKEYINFO k;
  269.     bool_t    mstatus,
  270.         psvstatus;
  271.  
  272.     flush_output();
  273.  
  274.     mstatus = (usemouse && State == NORMAL);
  275.     psvstatus = (keystrokes >= PSVKEYS);
  276.     /*
  277.      * We don't have to give control to any other thread
  278.      * if neither of these conditions is true.
  279.      */
  280.     if (mstatus || psvstatus) {
  281. #ifndef NOMOUSE
  282.         if (mstatus)
  283.         showmouse();
  284. #endif
  285.         if (psvstatus && DosSemWait(psvsema, SEM_IMMEDIATE_RETURN)
  286.                             == ERROR_SEM_TIMEOUT) {
  287.         /*
  288.          * If psvsema is set, clear it.
  289.          */
  290.         DosSemClear(psvsema);
  291.         }
  292.         DosSemClear(control);
  293.     }
  294.     /*
  295.      * Start of non-critical section.
  296.      *
  297.      * Wait for character from keyboard.
  298.      */
  299.     KbdCharIn((PKBDKEYINFO) &k, IO_WAIT, 0);
  300.     /*
  301.      * End of non-critical section.
  302.      */
  303.     if (mstatus || psvstatus) {
  304.         DosSemRequest(control, SEM_INDEFINITE_WAIT);
  305. #ifndef NOMOUSE
  306.         if (mstatus)
  307.         hidemouse();
  308. #endif
  309.     }
  310.     if (++keystrokes >= PSVKEYS)
  311.         lastevent = clock();
  312.     /*
  313.      * Now deal with the keypress information.
  314.      */
  315.     if ((unsigned char) k.chChar == (unsigned char) 0xe0) {
  316.     /*
  317.      * It's (probably) a function key.
  318.      */
  319.         if (k.chScan == 0x53)
  320.         /*
  321.          * It's the delete key.
  322.          */
  323.         return State == NORMAL ? 'x' : '\b';
  324.          /* else */
  325.         if (State == NORMAL) {
  326.         /*
  327.          * Assume it must be a function key.
  328.          */
  329.         switch (k.chScan) {
  330.             case 0x3b: return(K_HELP);
  331.             /* F1 key */
  332.             case 0x47: return('H');
  333.             /* home key */
  334.             case 0x48: return('k');
  335.             /* up arrow key */
  336.             case 0x49: return(CTRL('B'));
  337.             /* page up key */
  338.             case 0x4b: return('\b');
  339.             /* left arrow key */
  340.             case 0x4d: return(' ');
  341.             /* right arrow key */
  342.             case 0x4f: return('L');
  343.             /* end key */
  344.             case 0x50: return('j');
  345.             /* down arrow key */
  346.             case 0x51: return(CTRL('F'));
  347.             /* page down key */
  348.             case 0x52: return('i');
  349.             /* insert key */
  350.             default:
  351.             /* just ignore it ... */
  352.             continue;
  353.         }
  354.         /*
  355.          * If we aren't in command mode, 0xe0
  356.          * is a perfectly legitimate
  357.          * character, & we can't really tell
  358.          * whether or not it's supposed to be
  359.          * a function key, so we just have to
  360.          * return it as is.
  361.          */
  362.         }
  363.     }
  364.     return (unsigned char) k.chChar;
  365.     }
  366. }
  367.  
  368. void
  369. outchar(int c)
  370. {
  371.     curcell [0] = c;
  372.     VioWrtNCell((PBYTE) curcell, 1,